#include <iostream>
#include <sw/redis++/redis++.h>
#include "../util.hpp"

/*
    string类型命令的基本使用
*/

void test1(sw::redis::Redis& redis)
{
    // set和get
    redis.flushall();
    redis.set("key1", "111");
    sw::redis::OptionalString s = redis.get("key1");
    std::cout << s.value() << std::endl;
    // OptionalString 对应的是c++17里的Optional<std::string>类型，因为get有时能得到有效值，有时得到的是nil，用string不方便存储
    // 如果返回指针，空间问题释放

    s = redis.get("key20");
    //std::cout << s.value() << std::endl; // 错误
    // 此处如果直接打印会抛出异常std::bad_optional_access
    // 因为key20不存在，get得不到任何数据，此时如果调用value()函数就会报错
    // 处理方法：1、捕获异常 2、先判断再输出
    if(s)
        std::cout << s.value() << std::endl;
}

void test2(sw::redis::Redis& redis)
{
    // mset和mget使用
    redis.flushall();
    // 方法一：列表初始化描述的多个键值对
    //redis.mset({std::make_pair("key1", "111"), {"key2", "222"}, {"key3", "333"}});

    // 方法二：vector
    std::vector<std::pair<std::string, std::string>> v = {{"key1", "111"}, {"key2", "222"}, {"key3", "333"}};
    redis.mset(v.begin(), v.end());


    std::vector<sw::redis::OptionalString> result;
    auto it = std::back_inserter(result);
    redis.mget({"key1", "key2", "key4"}, it);
    printContainerOptional(result);
}

void test3(sw::redis::Redis& redis)
{
    // 给key设置过期时间EX、PX和NX、XX（没有提供关于过期时间的函数 也没有提供setnx和setxx，全部结合到了set中）
    redis.flushall();
    redis.set("key1", "111", std::chrono::seconds(30), sw::redis::UpdateType::NOT_EXIST); // 相当于使用了NX和EX选项
    std::this_thread::sleep_for(std::chrono::seconds(3));
    long long n = redis.ttl("key1");
    std::cout << "ttl=" << n << std::endl;
    std::cout << redis.get("key1").value() << std::endl;

    redis.set("key1", "222", 0, sw::redis::UpdateType::NOT_EXIST); //0代表不设置时间
    std::cout << redis.get("key1").value() << std::endl;
}


void test4(sw::redis::Redis& redis)
{
    // setrange 和 getrange
    redis.flushall();
    redis.mset({std::make_pair("key1", "abcdefghijklmnop"), {"key2", "天天打游戏"}, {"key3", "333"}});

    std::string s = redis.getrange("key1", 1, 5);
    std::cout << s << std::endl;

    s = redis.getrange("key2", 0, 5);
    std::cout << s << std::endl;

    long long n = redis.setrange("key1", 1, "xyz");
    std::cout << n << std::endl;
    std::cout << "strlen=" << redis.strlen("key1") << std::endl;
    std::cout << redis.getrange("key1", 0, -1) << std::endl;

    std::cout << "不存在的key:" << redis.getrange("key4", 0, 10) << std::endl; //对应不存在的key返回空串
}

void test5(sw::redis::Redis& redis)
{
    // incr 和 decr
    redis.flushall();
    redis.mset({std::make_pair("key1", "111"), {"key2", "天天打游戏"}, {"key3", "333"}});

    long long n = redis.incr("key1");
    std::cout << n << std::endl;

    n = redis.decr("key3");
    std::cout << n << std::endl;

    // n = redis.incr("key2"); // 对一个非整数incr会抛出异常
    // std::cout << n << std::endl;

    n = redis.incr("key5"); // 对一个不存在的keyincr，和正常一样，当作0加1,然后新增key5
    std::cout << n << std::endl;
}


int main()
{
    sw::redis::Redis redis("tcp://127.0.0.1:6379");
    // test1(redis);
    // test2(redis);
    // test3(redis);
    // test4(redis);
    test5(redis);

    return 0;
}